<?php
class ss_dao_query{
	private $what=array();
	private $from=array();
	private $where=array();
	private $limitNum=null;
	private $limitStart=null;
	private $source=array();
	private $alias=array();
	private $values=array();
	private $order=array();
	private $set=array();

	public function select(){
		//$request='SELECT ';
		/*ss_error::log($this->compAs($this->what),'SELECT');
		ss_error::log($this->compAs($this->from),'FROM');
		ss_error::log($this->compWhere($this->where),'WHERE');*/
		if(count($this->what)>0) {
			$request='SELECT '.$this->compAs($this->what);
		} else {
			$request='SELECT *';
		}
		if(count($this->from)>0) $request.=' FROM '.$this->compAs($this->from);
		if(count($this->where)>0) $request.=' WHERE '.$this->compWhere($this->where);
		if(count($this->order)>0) $request.=' ORDER BY '.implode(', ',$thos->order);
		if(!is_null($this->limitNum)){
			//$request.=' LIMIT '.$this->limitNum;
			$request.=' LIMIT :limitnum';
			$this->values[':limitnum']=$this->limitNum;
			//if(!is_null($this->limitStart)) $request.=' OFFSET '.$this->limitStart;
			if(!is_null($this->limitStart)) {
				$request.=' OFFSET :limitstart';
			$this->values[':limitstart']=$this->limitStart;
			}
		}
		return $request;
	}
	
	public function update(){
		$request='UPDATE';
		if(count($this->from)>0) $request.=' '.$this->compAs($this->from);
		if(count($this->set)>0) $request.=' SET '.$this->compSet($this->set);
		if(count($this->where)>0) $request.=' WHERE '.$this->compWhere($this->where);
		/*if(count($this->order)>0) $request.=' ORDER BY '.implode(', ',$thos->order);
		if(!is_null($this->limitNum)){
			//$request.=' LIMIT '.$this->limitNum;
			$request.=' LIMIT :limitnum';
			$this->values[':limitnum']=$this->limitNum;
			//if(!is_null($this->limitStart)) $request.=' OFFSET '.$this->limitStart;
			if(!is_null($this->limitStart)) {
				$request.=' OFFSET :limitstart';
			$this->values[':limitstart']=$this->limitStart;
			}
		}*/
		return $request;
	}
	
	public function insert(){
		$request='INSERT INTO ';
		if(count($this->from)>0) $request.=' '.$this->compAs($this->from);
		if(isset($this->multival)){
			if(count($this->multival)>0) $request.=$this->compMultival($this->multival);
		} else {
			if(count($this->set)>0) $request.=' SET '.$this->compSet($this->set);
		}
		return $request;
	}
	
	public function delete(){
		$request='DELETE FROM ';
		if(count($this->from)>0) $request.=' '.$this->compAs($this->from);
		if(count($this->where)>0) $request.=' WHERE '.$this->compWhere($this->where);
		return $request;
	}
	
	public function set($set){
		//ss_error::log($set,'Set input');
		$result=array();
		if(!is_array($set)) $set=array($set);
		if(array_key_exists('lft',$set))$set=array($set);
		//ss_error::log($where,'Where');
		foreach($set as $val){
			if(is_array($val)){
				if(array_key_exists('lft',$val)){
					foreach(array('lft','rgt') as $pos) $$pos=$this->setVal($val[$pos]);
					$this->set[]=array('lft'=>$lft,'rgt'=>$rgt);
				} else {
					ss_error::log('Key->val set');
					foreach($val as $lft=>$rgt){
						//ss_error::log($rgt,$lft);
						if(empty($rgt) && ($rgt!==0 && $rgt!=='0' && $rgt!==false)) {
							//ss_error::log('Setting '.$lft.' to NULL. Is zero: '.($rgt=='0'?'true':'false'));
							$rgt=NULL;
						}
						//ss_error::log($rgt,'rgt0');
						if(!is_string($rgt) || $rgt[0]!==':'){
							$this->set[]=array('lft'=>$lft,'rgt'=>':'.$lft);
							$this->values[':'.$lft]=$rgt;
						} else {
							$this->set[]=array('lft'=>$lft,'rgt'=>$rgt);
						}
						//ss_error::log($rgt,$lft);
					}
				}
				
				
			} else {
				$this->set[]=$val;
			}
		}
		//ss_error::log($this->set,'Set result');
		//ss_error::log($this->values,'Set values');
		return $this;
	}
	
	protected function compMultival($data){
		$result='(`'.implode('`,`',$this->fields).'`) VALUES';
		foreach($data as $row){
			$rows[]='('.implode(',',$row).')';
		}
		$result.=implode(',',$rows);
		return $result;
	}
	
	public function multiSet($set){
		$this->fields=array_keys($set[0]);
		foreach($set as $row){
			$result=array();
			if(!is_array($row)) $row=array($row);
			if(array_key_exists('lft',$row))$row=array($row);
			//ss_error::log($where,'Where');
			foreach($row as $val){
				if(is_array($val)){
					if(array_key_exists('lft',$val)){
						//foreach(array('lft','rgt') as $pos) $$pos=$this->setVal($val[$pos]);
						$result[]=$this->setVal($val['rgt']);
						//$this->set[]=array('lft'=>$lft,'rgt'=>$rgt);
					} else {
						foreach($val as $lft=>$rgt){
						if(empty($rgt) && $rgt!==0 && $rgt!==false) $rgt=NULL;
							$result[]=$rgt;
							/*if(empty($rgt)) $rgt=NULL;
							//ss_error::log($rgt,'rgt0');
							if(!is_string($rgt) || $rgt[0]!==':'){
								$this->set[]=array('lft'=>$lft,'rgt'=>':'.$lft);
								$this->values[':'.$lft]=$rgt;
							} else {
								$this->set[]=array('lft'=>$lft,'rgt'=>$rgt);
							}*/
						}
					}
					
					
				} else {
					$result[]=$val;
				}
			}
			$this->multival[]=$result;
		}
		return $this;
	}
	
	public function values(){
		return $this->values;
	}
	
	private function compAs($data){
		$comp=array();
		foreach($data as $key=>$val){
			if(is_string($key)){
				$comp[]=$val.' as `'.$key.'`';
			} else {
				$comp[]=$val;
			}
		}
		return implode(', ',$comp);
	}
	
	private function compWhere($data){
		$comp=array();
		foreach($data as $val){
			$result='';
			if(count($comp)>0 && isset($val['ar'])) $result.=$val['ar'].' ';
			$result.=(is_array($val['lft'])?$this->compWhere($val['lft']):$val['lft']).' ';
			$result.=$val['cmp'].' ';
			$result.=(is_array($val['rgt'])?$this->compWhere($val['lft']):$val['rgt']);
			$comp[]=$result;
		}
		return implode(' ',$comp);
	}
	
	private function compSet($data){
		$comp=array();
		foreach($data as $val){
			$result='';
			//if(count($comp)>0 && isset($val['ar'])) $result.=$val['ar'].' ';
			$result.=(is_array($val['lft'])?$this->compSet($val['lft']):$val['lft']).' ';
			$result.='=';
			//$result.=$val['cmp'].' ';
			$result.=(is_array($val['rgt'])?$this->$result($val['lft']):$val['rgt']);
			$comp[]=$result;
		}
		return implode(', ',$comp);
	}
	
	public function what($what){
		if(!is_array($what)) $what=array($what);
		if(array_key_exists('col',$what) || array_key_exists('com',$what)) $what=array($what);
		foreach($what as $key=>$val){
			$result='';
			$as=(is_string($key) ? $key : count($this->what));
			if(is_array($val)){
				if(isset($val['as'])) $as=$val['as'];
				$this->what[$as]=$this->setVal($val);
			} else {
				$this->what[$as]=$this->formatCol($val);
			}
		}
		return $this;
	}
	
	public function from($from){
		if(!is_array($from)) $from=array($from);
		foreach($from as $key=>$val){
			$result='';
			$as=(is_string($key) ? $key : count($this->what));
			if(is_array($val)){
				if(isset($val['as'])) $as=$val['as'];
				$this->from[$as]=$this->setVal($val);
			} else {
				$this->from[$as]=$this->formatCol($val);
			}
			//if(!in_array($as,$this->alias)) $this->alias[]=$as;
		}
		return $this;
	}
	
	public function where($where){
		if(count($where)==1 && empty($where[0])) return $this;
		$this->where=$this->whereRec($where);
		return $this;
	}
	
	public function order($order=array()){
		foreach($order as $val){
			if(is_array($val)){
				$this->order[]=setVal($val);
			} else {
				$this->order[]=formatCol($val);
			}
		}
		return $this;
		
	}
	
	public function limit($num=null,$start=null){
		$this->limitNum=$num;
		$this->limitStart=$start;
		return $this;
	}
	
	public function whereRec($where){
		$result=array();
		if(!is_array($where)) $where=array($where);
		if(array_key_exists('lft',$where))$where=array($where);
		//ss_error::log($where,'Where');
		foreach($where as $val){
			if(is_array($val)){
				if(array_key_exists('lft',$val)){
					$ar=(isset($val['ar'])?$val['ar']:'AND');
					foreach(array('lft','rgt') as $pos){
						if(is_array($val[$pos]) && array_key_exists('sub',$val[$pos])){
							$$pos=$this->whereRec($val[$pos]['sub']);
						} else {
							$$pos=$this->setVal($val[$pos]);
						}
					}
					$cmp=((array_key_exists('cmp',$val)) ? ($val['cmp']===false ? '' : $val['cmp'] ):'=');
					$result[]=array('ar'=>$ar,'lft'=>$lft,'cmp'=>$cmp,'rgt'=>$rgt);
				} else {
					foreach($val as $lft=>$rgt){
						if($rgt=='*'){
							
						}elseif($rgt[0]!==':'){
							$result[]=array('lft'=>$lft,'cmp'=>'=','rgt'=>':'.$lft);
							$this->values[':'.$lft]=$rgt;
						} else {
							$result[]=array('lft'=>$lft,'cmp'=>'=','rgt'=>$rgt);
						}
					}
				}
				
				
			} else {
				$result[]=$val;
			}
			
		}
		return $result;
	}
	
	private function setVal($data){
		if(is_array($data)){
			if(isset($data['com'])){
				return $data['com'];
			} elseif(isset($data['col'])){
				return $this->formatCol($data['col']);
			}
		}
		return $this->formatCol($data);
	}
	
	private function formatCol($col){
		return ('`'.str_replace('.','`.`',$col).'`'); 
	}
}
?>